/********************************************************************
	created:	2010/5/6   13:48
	filename: 	zr_atomic_long.h
	author:		zxh
	purpose:	atomic operator
*********************************************************************/
#ifndef _ZR_ATOMIC_LONG_H_
#define _ZR_ATOMIC_LONG_H_


#ifndef _WIN32

inline long InterlockedIncrement (volatile long *value)
{
	long tmp = 1;
	unsigned long addr = reinterpret_cast<unsigned long> (value);
	asm( "lock ; xadd %0, (%1)" : "+r"(tmp) : "r"(addr) );
	return tmp + 1;
}

inline long InterlockedDecrement (volatile long *value)
{
	long tmp = -1;
	unsigned long addr = reinterpret_cast<unsigned long> (value);
	asm( "lock ; xadd %0, (%1)" : "+r"(tmp) : "r"(addr) );
	return tmp - 1;
}

inline long InterlockedExchange (volatile long *value, long rhs)
{
	unsigned long addr = reinterpret_cast<unsigned long> (value);
	// The XCHG instruction automatically follows LOCK semantics
	asm( "xchg %0, (%1)" : "+r"(rhs) : "r"(addr) );
	return rhs;
}

inline long InterlockedExchangeAdd (volatile long *value, long rhs)
{
	unsigned long addr = reinterpret_cast<unsigned long> (value);
	asm( "lock ; xadd %0, (%1)" : "+r"(rhs) : "r"(addr) );
	return rhs;
}

#endif //_WIN32

class  hy_atomic_long
{
public:
	/// Initialize <value_> to 0.
	hy_atomic_long (void):value_(0) {}

	/// Initialize <value_> to c.
	hy_atomic_long (long c):value_(c) {}

	hy_atomic_long (const hy_atomic_long &rhs):value_(rhs.value_) {}

	/// Atomically pre-increment <value_>.
	long operator++ (void)
	{
		return InterlockedIncrement (&this->value_);
	}

	/// Atomically post-increment <value_>.
	long operator++ (int)
	{
		return ++*this - 1;
	}

	/// Atomically increment <value_> by rhs.
	long operator+= (long rhs)
	{
		return InterlockedExchangeAdd (const_cast<long *> (&this->value_),
			rhs) + rhs; 
	}

	/// Atomically pre-decrement <value_>.
	long operator-- (void)
	{
		return InterlockedDecrement (const_cast<long *> (&this->value_));
	}

	/// Atomically post-decrement <value_>.
	long operator-- (int)
	{
		return --*this + 1;
	}

	/// Atomically decrement <value_> by rhs.
	long operator-= (long rhs)
	{
		return InterlockedExchangeAdd (const_cast<long *> (&this->value_),
			-rhs) - rhs;
	}

	/// Atomically compare <value_> with rhs.
	bool operator== (long rhs) const
	{
		return (this->value_ == rhs);
	}

	/// Atomically compare <value_> with rhs.
	bool operator!= (long rhs) const
	{
		return (this->value_ != rhs);
	}

	/// Atomically check if <value_> greater than or equal to rhs.
	bool operator>= (long rhs) const
	{
		return (this->value_ >= rhs);
	}

	/// Atomically check if <value_> greater than rhs.
	bool operator> (long rhs) const
	{
		return (this->value_ > rhs);
	}

	/// Atomically check if <value_> less than or equal to rhs.
	bool operator<= (long rhs) const
	{
		return (this->value_ <= rhs);
	}

	/// Atomically check if <value_> less than rhs.
	bool operator< (long rhs) const
	{
		return (this->value_ < rhs);
	}

	/// Atomically assign rhs to <value_>.
	hy_atomic_long &operator= (long rhs)
	{
		InterlockedExchange (const_cast<long *> (&this->value_), rhs);
		return *this;
	}

	/// Atomically assign <rhs> to <value_>.
	hy_atomic_long &operator= (const hy_atomic_long &rhs)
	{
		InterlockedExchange (const_cast<long *> (&this->value_), rhs.value_);
		return *this;
	}

	/// Explicitly return <value_>.
	long value (void) const
	{
		return value_;
	}

	/// Dump the state of an object.
	//void dump (void) const;

	/// Explicitly return <value_> (by reference).
	volatile long &value_i (void)
	{
		return value_;
	}

private:

	/// Current object decorated by the atomic op.
	volatile long value_;
};

#endif //_ATOMIC_LONG_H_
